package model

import (
	"errors"
	"fmt"
	"github.com/spf13/cast"
	"go-vue/admin/conf"
	"log"
)

// SystemDepart 系统角色
type SystemDepart struct {
	DepartId    int64      `xorm:"autoincr depart_id"`
	DepartLevel int64      `xorm:"depart_level"`
	DepartPid   int64      `xorm:"depart_pid"`
	DepartSort  int64      `xorm:"depart_sort"`
	DepartName  string     `xorm:"depart_name"`
	State       conf.State `xorm:"state"`
}

func (depart *SystemDepart) One() *SystemDepart {
	exist, err := conf.DbEngine.Get(depart)
	if err != nil || exist == false {
		return nil
	}
	return depart
}

// GetAllInitDepart 获取系统所有部门(部门管理编辑用)
func (depart *SystemDepart) GetAllInitDepart() *InitOutput {
	var departList []SystemDepart
	err := conf.DbEngine.Where("state = ?",conf.StateOn).OrderBy("depart_sort asc").Cols("depart_id,depart_pid,depart_name").Find(&departList)
	if err != nil {
		return nil
	}
	result := &InitOutput{
	}
	var listInitSource = make(map[string]*InitOutputSource,0)
	var listInitNodeTree []*InitOutputTreeNode
	if len(departList) > 0 {
		for _, item := range departList {
			value := cast.ToString(item.DepartId)
			tmp := &InitOutputSource{
				Label: item.DepartName,
				Pid: cast.ToString(item.DepartPid),
				Value: value,
			}
			listInitSource[value] = tmp
		}
		listInitNodeTree = depart.BuildDepartChildInit(0, departList)
	}
	result.Source = listInitSource
	result.TreeNode = listInitNodeTree
	return result
}

// BuildDepartChildInit 递归获取子部门(部门管理编辑用)
func (depart *SystemDepart) BuildDepartChildInit(depart_pid int64, departList []SystemDepart) []*InitOutputTreeNode {
	var treeList []*InitOutputTreeNode
	for _, v := range departList {
		if depart_pid == v.DepartPid {
			node := &InitOutputTreeNode{
				Label:    v.DepartName,
				Value:    cast.ToString(v.DepartId),
				Children: nil,
			}
			child := v.BuildDepartChildInit(v.DepartId, departList)
			if len(child) != 0 {
				node.Children = child
			}
			treeList = append(treeList, node)
		}
	}
	return treeList
}

// SystemDepartEditList 部门列表(部门管理编辑用)
type SystemDepartEditList struct {
	Id       int64                   `json:"id"`
	ParentId int64                   `json:"parentId"`
	Level    int64                   `json:"level"`
	Sort     int64                   `json:"sort"`
	Name     string                  `json:"name"`
	State    conf.State              `json:"state"`
	Children []*SystemDepartEditList `json:"children,omitempty"`
}

// GetAllEditDepart 获取系统所有部门(部门管理编辑用)
func (depart *SystemDepart) GetAllEditDepart() []*SystemDepartEditList {
	var departList []SystemDepart
	err := conf.DbEngine.OrderBy("depart_sort asc").Find(&departList)
	if err != nil {
		log.Println(err)
		return nil
	}

	var listEdit []*SystemDepartEditList
	if len(departList) > 0 {
		listEdit = depart.BuildDepartChildEdit(0, departList)
	}
	return listEdit
}

// BuildDepartChildEdit 递归获取子部门(部门管理编辑用)
func (depart *SystemDepart) BuildDepartChildEdit(depart_pid int64, departList []SystemDepart) []*SystemDepartEditList {
	var treeList []*SystemDepartEditList
	for _, v := range departList {
		if depart_pid == v.DepartPid {
			node := &SystemDepartEditList{
				Id:       v.DepartId,
				ParentId: v.DepartPid,
				Level:    v.DepartLevel,
				Name:     v.DepartName,
				State:    v.State,
				Sort:     v.DepartSort,
				Children: nil,
			}
			child := v.BuildDepartChildEdit(v.DepartId, departList)
			if len(child) != 0 {
				node.Children = child
			}
			treeList = append(treeList, node)
		}
	}
	return treeList
}

// SaveEditDepart 编辑系统部门(部门管理编辑用)
func (depart *SystemDepart) SaveEditDepart(input *SystemDepartEditList) (id int64, err error) {
	//主表信息
	departInfo := &SystemDepart{
		DepartId:   input.Id,
		DepartPid:  input.ParentId,
		DepartName: input.Name,
		State:      input.State,
	}
	if input.Id != 0 {
		//更新主表
		_, err = conf.DbEngine.Where("depart_id = ?", input.Id).Cols("depart_pid,depart_name,state").Update(departInfo)
		if err != nil {
			return 0, err
		}
		id = input.Id
	} else { // 新增
		max := &SystemDepart{}
		//获取最大排序 直接更新
		_, err := conf.DbEngine.Where("depart_pid=?", input.ParentId).OrderBy("depart_sort desc").Cols("depart_sort").Get(max)
		if err != nil {
			return 0, err
		}
		departInfo.DepartSort = max.DepartSort + 1

		level := &SystemDepart{}
		//当前需要更新到哪个层级
		_, err = conf.DbEngine.Where("depart_id=?", input.ParentId).Cols("depart_level").Get(level)
		if err != nil {
			return 0, err
		}
		departInfo.DepartLevel = level.DepartLevel + 1

		log.Printf("max %+v \n", max)

		_, err = conf.DbEngine.Insert(departInfo)
		if err != nil {
			return 0, err
		}
		id = departInfo.DepartId
	}

	return id, err
}

// SortEditDepart 系统菜单排序(菜单管理编辑用)
func (depart *SystemDepart) SortEditDepart(input *MenuSortInput) error {
	depart.DepartId = input.DropId
	res := depart.One()
	if res == nil {
		return errors.New("更改节点不存在")
	}

	dragging := &SystemDepart{
		DepartId: input.DraggingId,
	}
	res = dragging.One()
	if res == nil {
		return errors.New("拖拽的节点不存在")
	}

	//拖拽到新节点里面
	if input.DropType == "inner" {
		dragging.DepartPid = depart.DepartId

		max := &SystemDepart{}
		//获取最大排序 直接更新
		_, err := conf.DbEngine.Where("depart_pid=?", depart.DepartId).OrderBy("depart_sort desc").Cols("depart_sort").Get(max)
		if err != nil {
			return err
		}
		dragging.DepartSort = max.DepartSort + 1

		//更新数据
		_, err = conf.DbEngine.Where("depart_id = ?", dragging.DepartId).Cols("depart_pid,depart_sort").Update(dragging)
		if err != nil {
			return err
		}
		return nil
	}

	var (
		sql    string
		sqlOld string
	)

	//同一个级别排序
	if dragging.DepartPid == depart.DepartPid {
		if dragging.DepartSort < depart.DepartSort { //拖动节点顺序变大
			if input.DropType == "before" {
				sql = fmt.Sprintf("update system_depart set depart_sort = depart_sort-1 where depart_pid = %d and depart_sort > %d and depart_sort < %d", depart.DepartPid, dragging.DepartSort, depart.DepartSort)
				dragging.DepartSort = depart.DepartSort - 1
			} else if input.DropType == "after" {
				sql = fmt.Sprintf("update system_depart set depart_sort = depart_sort-1 where depart_pid = %d and depart_sort > %d and depart_sort <= %d", depart.DepartPid, dragging.DepartSort, depart.DepartSort)
				dragging.DepartSort = depart.DepartSort
			}
		} else { //拖动节点顺序变小
			if input.DropType == "before" {
				sql = fmt.Sprintf("update system_depart set depart_sort = depart_sort+1 where depart_pid = %d and depart_sort >= %d and depart_sort < %d", depart.DepartPid, depart.DepartSort, dragging.DepartSort)
				dragging.DepartSort = depart.DepartSort
			} else if input.DropType == "after" {
				sql = fmt.Sprintf("update system_depart set depart_sort = depart_sort+1 where depart_pid = %d and depart_sort > %d and depart_sort < %d", depart.DepartPid, depart.DepartSort, dragging.DepartSort)
				dragging.DepartSort = depart.DepartSort + 1
			}
		}
	} else { //从别的节点子项目拖到新的节点子项目
		//更新老节点的排序
		sqlOld = fmt.Sprintf("update system_depart set depart_sort = depart_sort-1 where depart_pid = %d and depart_sort > %d", dragging.DepartPid, dragging.DepartSort)

		dragging.DepartPid = depart.DepartPid
		dragging.DepartLevel = depart.DepartLevel
		if input.DropType == "before" {
			sql = fmt.Sprintf("update system_depart set depart_sort = depart_sort+1 where depart_pid = %d and depart_sort >= %d", depart.DepartPid, depart.DepartSort)
			dragging.DepartSort = depart.DepartSort
		} else if input.DropType == "after" {
			sql = fmt.Sprintf("update system_depart set depart_sort = depart_sort+1 where depart_pid = %d and depart_sort > %d", depart.DepartPid, depart.DepartSort)
			dragging.DepartSort = depart.DepartSort + 1
		}
	}

	session := conf.DbEngine.NewSession()
	defer session.Close()

	session.Begin()
	//更新老节点的排序
	if sqlOld != "" {
		_, err := session.Exec(sqlOld)
		if err != nil {
			session.Rollback()
			return err
		}
	}
	//先更新其他数据的顺序
	_, err := session.Exec(sql)
	if err != nil {
		session.Rollback()
		return err
	}
	//更新拖拽数据顺序
	_, err = session.Where("depart_id = ?", dragging.DepartId).Cols("depart_pid,depart_sort,menu_level").Update(dragging)
	if err != nil {
		session.Rollback()
		return err
	}
	err = session.Commit()
	if err != nil {
		session.Rollback()
		return err
	}
	return nil
}

// DelEditDepart 删除列表
func (depart *SystemDepart) DelEditDepart(input *DeleteInputIds) error {
	delList := depart.treeDel(input.Ids, input.Ids)
	fmt.Printf("delList === %+v\n", delList)
	if len(delList) == 0 {
		return errors.New("不存在删除的节点")
	}

	//删除主表
	_, err := conf.DbEngine.In("depart_id", delList).Delete(depart)
	if err != nil {
		return err
	}
	return nil
}

//递归删除
func (depart *SystemDepart) treeDel(ids []int64, exist []int64) []int64 {
	list := make([]SystemDepart, 0)
	err := conf.DbEngine.In("depart_pid", ids).Cols("depart_id").Find(&list)
	if err != nil {
		return nil
	}
	if len(list) > 0 {
		newIds := make([]int64, 0)
		for _, item := range list {
			newIds = append(newIds, item.DepartId)
		}
		exist = append(exist, newIds...)
		return depart.treeDel(newIds, exist)
	}
	return exist
}
